<?php
/*
 * @Author: 杨红兵 
 * @Date: 2022-10-02 10:45:26 
 * @Last Modified by: 杨红兵
 * @Last Modified time: 2022-10-02 10:48:20
 */

namespace app\libraries\utils\queue\driver;

use Exception;
use RedisException;
use think\helper\Str;
use think\queue\connector\Redis as ConnectorRedis;

class Redis extends ConnectorRedis
{
    public static function __make($config)
    {
        if (!extension_loaded('redis')) {
            throw new Exception('redis扩展未安装');
        }

        $redis = new class($config)
        {
            protected $config;
            protected $client;

            public function __construct($config)
            {
                $this->config = $config;
                $this->client = $this->createClient();
            }

            protected function createClient()
            {
                $config = $this->config;
                $func   = $config['persistent'] ? 'pconnect' : 'connect';

                $client = new \Redis;
                if (strpos($config['host'], '/') !== false) {
                    $client->$func($config['host']);
                } else {
                    $client->$func($config['host'], $config['port'], $config['timeout']);
                }

                if ('' != $config['password']) {
                    $client->auth($config['password']);
                }

                if (0 != $config['select']) {
                    $client->select($config['select']);
                }
                return $client;
            }

            public function __call($name, $arguments)
            {
                try {
                    return call_user_func_array([$this->client, $name], $arguments);
                } catch (RedisException $e) {
                    if (Str::contains($e->getMessage(), 'went away')) {
                        $this->client = $this->createClient();
                    }

                    throw $e;
                }
            }
        };

        return new self($redis, $config['queue'], $config['retry_after'] ?? 60, $config['block_for'] ?? null);
    }

    /**
     * 创建Redis任务体
     *
     * @Author YangHB
     * @DateTime 2022-10-02 15:20:13
     *
     * @param mixed $job
     * @param string $data
     * @return array
     */
    protected function createPayloadArray($job, $data = '')
    {
        $result = parent::createPayloadArray($job, $data);
        if (!isset($result['id'])) {
            $result['id'] = get_sequuid(true);
        }
        return $result;
    }

    /**
     * 获取队列名
     *
     * @param string|null $queue
     * @return string
     */
    protected function getQueue($queue)
    {
        $queue = $queue ?: $this->default;
        $project = config('app.project_name');
        return "{queues:{$project}_{$queue}}";
    }
}
